﻿#ifndef JZNODE_PROGRAM_H_
#define JZNODE_PROGRAM_H_

#include <QThread>
#include "JZNode.h"
#include "JZNodeEvent.h"
#include "JZNodeIR.h"
#include "JZNodeFunctionDefine.h"
#include "JZNodeObject.h"
#include "JZScriptEnvironment.h"

//NodeRange
struct NodeRange
{
    NodeRange();

    int start;
    int debugStart;
    int end;
};
QDataStream &operator<<(QDataStream &s, const NodeRange &param);
QDataStream &operator>>(QDataStream &s, NodeRange &param);

//NodeParamInfo
struct NodeParamInfo
{
    int id;
    bool isInput;
    JZParam define;
};
QDataStream &operator<<(QDataStream &s, const NodeParamInfo &param);
QDataStream &operator>>(QDataStream &s, NodeParamInfo &param);

//NodeInfo
struct NodeInfo
{        
    NodeInfo();    
    const NodeParamInfo *param(int id) const;
    
    QString name;
    int id;
    int type;
    bool isFlow;       
    
    //paramIn,paramOut 不保存全部的节点，只保存运行时存在的节点信息
    QList<NodeParamInfo> params;
    QList<NodeRange> pcRanges;
};
QDataStream &operator<<(QDataStream &s, const NodeInfo &param);
QDataStream &operator>>(QDataStream &s, NodeInfo &param);

//JZFunctionDebugInfo
class JZFunctionDebugInfo
{
public:
    const JZParam *localParam(QString name) const;
    const JZParam *nodeParam(int id) const;

    QMap<int, NodeInfo> nodeInfo;
    QList<JZParam> localVariables;
    QMap<int, int> stackType;
};
QDataStream &operator<<(QDataStream &s, const JZFunctionDebugInfo &param);
QDataStream &operator>>(QDataStream &s, JZFunctionDebugInfo &param);

//JZNodeScript
class JZNodeScript
{    
public:    
    JZNodeScript();
    void clear();    

    const JZFunction *function(QString name) const;
    const JZFunctionDebugInfo *functionDebug(QString name) const;
    
    void copyTo(JZNodeScript *other) const;
    void saveToStream(QDataStream &s) const;
    void loadFromStream(QDataStream &s);

    QString itemPath;
    QString className;
    QList<JZNodeIRPtr> statmentList;
    QList<JZFunction> functionList;
    QList<JZFunctionDebugInfo> functionDebugList;

protected:
    Q_DISABLE_COPY(JZNodeScript);    
};
typedef QSharedPointer<JZNodeScript> JZNodeScriptPtr;

//JZNodeProgram
class JZNodeBuilder;
class JZNodeProgram 
{
public:
    JZNodeProgram();
    ~JZNodeProgram();

    bool isNull() const;

    void saveToStream(QDataStream &s) const;
    void loadFromStream(QDataStream &s);
    bool save(QString file);
    bool load(QString file,QString &error);    
    void clear();
    void copyTo(JZNodeProgram *other) const;
    
    void initEnv(JZScriptEnvironment *env) const;

    void setTypeMeta(JZNodeTypeMeta meta);
    const JZNodeTypeMeta &typeMeta() const;   

    QString applicationFilePath() const;
    
    const JZFunction* function(QString name) const;

    QList<JZNodeScript*> scriptList() const;

    JZNodeScript* script(QString path);
    const JZNodeScript *script(QString path) const;
    void addScript(JZNodeScriptPtr script);
    void removeScript(QString path);
    JZNodeScriptPtr takeScript(QString path);
    
    const JZFunctionDebugInfo *debugInfo(QString name) const;
    
protected:
    Q_DISABLE_COPY(JZNodeProgram);

    friend JZNodeBuilder;                
     
    QString m_filePath;
    QString m_error;

    JZNodeTypeMeta m_typeMeta;
    QMap<QString,JZNodeScriptPtr> m_scripts; 
    QMap<QString,JZParamDefine> m_variables;
};

#endif
